import 'dart:math';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class CanvasPage extends StatefulWidget {
  const CanvasPage({
    Key? key,
  }) : super(key: key);

  @override
  State<CanvasPage> createState() => _CanvasPageState();
}

class _CanvasPageState extends State<CanvasPage> with SingleTickerProviderStateMixin {
  ui.Image? _image;

  final ValueNotifier<Matrix4> _matrix = ValueNotifier(Matrix4.identity());

  late Matrix4 _lastMatrix = Matrix4.identity(); // 记录最后一次的运动，用于叠加上一次运动使用
  late final AnimationController _animationController;

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
      /// 获取本地图片
      _image = await CanvasUtils.getLocalImage();
      setState(() {});
    });

    _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 1000));

    super.initState();
  }

  @override
  void dispose() {
    _matrix.dispose();

    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        margin: const EdgeInsets.only(top: 20),
        child: Column(
          children: [
            /// 画布
            CustomPaint(
              size: const Size(300, 400),
              painter: Playground(image: _image, matrix: _matrix),
            ),

            const SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                /* IconButton.outlined(
                  onPressed: () => _onReset(),
                  icon: const Icon(Icons.refresh),
                ),
                IconButton.outlined(
                  onPressed: () => _onRotate(),
                  icon: const Icon(Icons.rotate_90_degrees_ccw_outlined),
                ),
                IconButton.outlined(
                  onPressed: () => _onMove(),
                  icon: const Icon(Icons.run_circle_outlined),
                ), */

                IconButton(
                  onPressed: () => _onReset(),
                  icon: const Icon(Icons.refresh),
                ),
                IconButton(
                  onPressed: () => _onRotate(),
                  icon: const Icon(Icons.rotate_90_degrees_ccw_outlined),
                ),
                IconButton(
                  onPressed: () => _onMove(),
                  icon: const Icon(Icons.run_circle_outlined),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  //...
  void _onReset() {
    _matrix.value = Matrix4.identity();
    _lastMatrix = Matrix4.identity();
  }

  void _onRotate() {
    /// 初始化矩阵
    /// 平移变换可以影响变换中心, 为了抵消平移变换带来的后果，在旋转之后，反向平移即可
    Matrix4 rotate90 = Matrix4.rotationZ(pi / 2);
    Matrix4 moveCenter = Matrix4.translationValues(50, 50, 0); // 平移距离最好是图片宽高的一半
    Matrix4 centerBack = Matrix4.translationValues(-50, -50, 0);
    // car_1.png图片给36 car_png图片给25

    /// 处理最后一次操作(修改变换中心，先平移后旋转，再恢复平移)
    /* _lastMatrix.multiply(moveCenter);
    _lastMatrix.multiply(rotate90); */

    /// 需要整个临时的矩阵，begin的值使用_lastMatrix才能是上一个运动的矩阵
    Matrix4 copy = _lastMatrix.clone(); // copy最后一次的运行矩阵
    // copy.multiply(moveCenter);
    // copy.multiply(rotate90);

    /* Matrix4 end = _lastMatrix.multiplied(centerBack); */
    // Matrix4 end = copy.multiplied(centerBack);

    Animation<Matrix4> anim = Matrix4Tween(begin: Matrix4.rotationZ(0), end: rotate90).animate(_animationController);

    anim.addListener(() {
      Matrix4 matrix4 = moveCenter.multiplied(anim.value).multiplied(centerBack);
      _matrix.value = copy.multiplied(matrix4); // 叠加矩阵
    });
    anim.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        // 记录最后一次运动矩阵
        _lastMatrix = _matrix.value;
      }
    });

    // 执行动画
    _animationController.forward(from: 0);
  }

  void _onMove() {
    Matrix4 move = Matrix4.translationValues(20, 0, 0);

    // copy 最后一次运动矩阵
    Matrix4 copy = _lastMatrix.clone();

    // 叠加矩阵
    // Matrix4 end = _lastMatrix.multiplied(move);

    Animation<Matrix4> anim = Matrix4Tween(begin: Matrix4.translationValues(0, 0, 0), end: move).animate(_animationController);

    anim.addListener(() {
      _matrix.value = copy.multiplied(anim.value); // 叠加矩阵
    });
    anim.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        // 记录最后一次运行
        _lastMatrix = _matrix.value;
      }
    });

    // 执行动画
    _animationController.forward(from: 0);
  }
}

/// 绘制画布
class Playground extends CustomPainter {
  final ui.Image? image;

  /// 用于矩阵变化
  final ValueListenable<Matrix4>? matrix;

  /* final TextPainter _textPainter = TextPainter(
    textAlign: TextAlign.center,
    textDirection: TextDirection.ltr,
  ); */

  Playground({
    this.image,
    this.matrix,
  }) : super(repaint: matrix);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..style = PaintingStyle.stroke
      ..color = Colors.redAccent;

    /// 绘制背景画布
    canvas.drawRect(Offset.zero & size, paint);

    /// 绘制文本
    /* double step = size.width / 10;
    for (var i = 0; i < 10; i++) {
      _textPainter.text = TextSpan(
        text: '$i',
        style: const TextStyle(
          fontSize: 12,
          color: Colors.black,
        ),
      );
      _textPainter.layout();

      /// 文字的宽度获取：_textPainter.size.width
      _textPainter.paint(canvas, Offset(i * step - _textPainter.size.width / 2, size.height + 5));
    } */

    /// 绘制本地图片
    if (image != null && matrix != null) {
      canvas.save(); // save() 操作会保存此前的所有绘制内容和 Canvas 状态。
      canvas.transform(matrix!.value.storage); // 可以通过 Matrix4 矩阵进行变换。而矩阵可以通过乘法进行变换的叠加
      drawCarImage(canvas, paint);
      canvas.restore(); // 当你调用 restore() 之后，会把 save() 到 restore() 之间所进行的操作与之前的内容进行合并。
    }
  }

  @override
  bool shouldRepaint(covariant Playground oldDelegate) {
    // return oldDelegate.image != image;
    return true;
  }

  /// 绘制本地车子图片
  drawCarImage(Canvas canvas, Paint paint) {
    // 给车子绘制边框
    Rect rect = Rect.fromLTWH(0, 0, image!.width.toDouble(), image!.height.toDouble());
    paint.color = Colors.orangeAccent;
    canvas.drawRect(rect, paint);

    /// 绘制本地图片
    canvas.drawImage(image!, Offset.zero, paint);
  }
}

/// 获取本地图片
/// final 对类进行修饰，其目的是为了关闭该类的继承体系。被 final 修饰的类无法被直接继承；
/// 另外 final 修饰的类无法在外部进行派生
/* final class CanvasUtils {
  static Future<ui.Image?> getLocalImage() async {
    ByteData byteData = await rootBundle.load('assets/car_1.png');

    return decodeImageFromList(byteData.buffer.asUint8List());
  }
} */
class CanvasUtils {
  static Future<ui.Image?> getLocalImage() async {
    ByteData byteData = await rootBundle.load('assets/car_1.png');

    return decodeImageFromList(byteData.buffer.asUint8List());
  }
}
